/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.modular.workorder.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import vip.xiaonuo.core.context.login.LoginContextHolder;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.modular.ass.entity.Ass;
import vip.xiaonuo.modular.ass.service.AssService;
import vip.xiaonuo.modular.pro.entity.Pro;
import vip.xiaonuo.modular.pro.service.ProService;
import vip.xiaonuo.modular.proplan.entity.ProPlan;
import vip.xiaonuo.modular.proplan.service.ProPlanService;
import vip.xiaonuo.modular.saleorder.entity.SaleOrder;
import vip.xiaonuo.modular.saleorder.service.SaleOrderService;
import vip.xiaonuo.modular.task.entity.Task;
import vip.xiaonuo.modular.task.enums.TaskExceptionEnum;
import vip.xiaonuo.modular.task.service.TaskService;
import vip.xiaonuo.modular.workorder.entity.WorkOrder;
import vip.xiaonuo.modular.workorder.enums.WorkOrderExceptionEnum;
import vip.xiaonuo.modular.workorder.enums.WorkOrderStatusEnum;
import vip.xiaonuo.modular.workorder.enums.WorkOrderTypeEnum;
import vip.xiaonuo.modular.workorder.mapper.WorkOrderMapper;
import vip.xiaonuo.modular.workorder.param.WorkOrderParam;
import vip.xiaonuo.modular.workorder.result.WorkOrderResult;
import vip.xiaonuo.modular.workorder.service.WorkOrderService;
import vip.xiaonuo.modular.workorderbill.entity.WorkOrderBill;
import vip.xiaonuo.modular.workorderbill.enums.WorkOrderBillEnum;
import vip.xiaonuo.modular.workorderbill.mapper.WorkOrderBillMapper;
import vip.xiaonuo.modular.workorderbill.service.WorkOrderBillService;
import vip.xiaonuo.modular.workordertask.entity.WorkOrderTask;
import vip.xiaonuo.modular.workordertask.service.WorkOrderTaskService;
import vip.xiaonuo.modular.workreport.entity.WorkReport;
import vip.xiaonuo.modular.workreport.service.WorkReportService;
import vip.xiaonuo.modular.workroute.entity.WorkRoute;
import vip.xiaonuo.modular.workroute.service.WorkRouteService;
import vip.xiaonuo.modular.worksteproute.entity.WorkStepRoute;
import vip.xiaonuo.modular.worksteproute.service.WorkStepRouteService;
import vip.xiaonuo.util.AutoCode;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工单表service接口实现类
 *
 * @author czw
 * @date 2022-05-25 10:31:14
 */
@Service
public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder> implements WorkOrderService {

    @Resource
    private ProService proService;

    @Resource
    private TaskService taskService;

    @Resource
    private WorkOrderTaskService workOrderTaskService;

    @Resource
    private WorkReportService workReportService;

    @Resource
    private WorkRouteService workRouteService;

    @Resource
    private WorkStepRouteService workStepRouteService;


    @Resource
    private SaleOrderService saleOrderService;

    @Resource
    private AssService assService;

    @Resource
    private ProPlanService proPlanServicep;

    @Resource
    private WorkOrderBillService workOrderBillService;

    @Override
    public PageResult<WorkOrderResult> page(WorkOrderParam workOrderParam) {

        Page<WorkOrderResult> page = this.baseMapper.page(PageFactory.defaultPage(), getQueryWrapper(workOrderParam));

        /*
         * ===============================================处理数据的准备工作 start ======================================
         */
        // 查询出所有的任务
        List<Task> taskList = taskService.list();
        // 将任务按照工单进行分组
        Map<Long,List<Task>> taskGroupByWorkOrderId = taskList.stream()
                .filter(item->ObjectUtil.isNotEmpty(item.getWorkOrderId()))
                .collect(Collectors.groupingBy(Task::getWorkOrderId));
        // 查询出所有的报工
        List<WorkReport> workReportList = workReportService.list();
        // 将报工按照工单进行分组
        Map<Long,List<WorkReport>> workReportGroupByWorkOrderId = workReportList.stream()
                .filter(item->ObjectUtil.isNotEmpty(item.getWorkOrderId()))
                .collect(Collectors.groupingBy(WorkReport::getWorkOrderId));

        // 查询出所有的工单任务关系数据(流程型工单专用)
        List<WorkOrderTask> workOrderTasks = workOrderTaskService.list();
        // 将工单任务关系按照工单进行分组(流程型工单专用)
        Map<Long, List<WorkOrderTask>> workOrderTaskGroupByWorkOrderId = workOrderTasks.stream()
                .filter(item->ObjectUtil.isNotEmpty(item.getWorkOrderId()))
                .collect(Collectors.groupingBy(WorkOrderTask::getWorkOrderId));
        // 设置一个Map key为销售订单id,value为所对应的全部销售订单
        List<SaleOrder> saleOrderList = saleOrderService.list();
        Map<Long,SaleOrder> saleOrderMap = saleOrderList.stream().collect(Collectors.toMap(SaleOrder::getId,a->a,(k1,k2)->k1));
        // 设置一个Map key为生产计划id,value为所对应的全部销售订单
        List<ProPlan> proPlanList = proPlanServicep.list();
        Map<Long,ProPlan> proPlanMap = proPlanList.stream().collect(Collectors.toMap(ProPlan::getId,a->a,(k1,k2)->k1));
        // 设置一个Map key为装配订单id,value为所对应的全部销售订单
        List<Ass> assList = assService.list();
        Map<Long,Ass> assMap = assList.stream().collect(Collectors.toMap(Ass::getId,a->a,(k1,k2)->k1));
        // 设置一个Map key为工单单据关系id,value为所对应的工单单据关系
        List<WorkOrderBill> workOrderBillList = workOrderBillService.list();
        Map<Long,WorkOrderBill> workOrderBillMap = workOrderBillList.stream().collect(Collectors.toMap(WorkOrderBill::getId,a->a,(k1,k2)->k1));
        /*
         * ===============================================处理数据的准备工作 end ======================================
         */

        // 获取分页返回的所有工单数据
        page.getRecords().forEach(item->{
            if(WorkOrderTypeEnum.PROCESS_WORK_ORDER.getCode().equals(item.getType())){
                /*
                 *
                 *
                 * (预留)流程型工单专有逻辑
                 *
                 *
                 *
                 */
            }
            /*
             * =======================================关联单据逻辑赋值 start =====================================
             */
            if (ObjectUtil.isNull(item.getBillId())){
                item.setWorkBillCode("");
            }
            else{
                Long type = workOrderBillMap.get(item.getBillId()).getType();
                Long billId = workOrderBillMap.get(item.getBillId()).getBillId();
                if (WorkOrderBillEnum.SaleOrder.getCode() == type){
                    item.setWorkBillCode(saleOrderMap.get(billId).getCode());
                }
                if (WorkOrderBillEnum.ProPlan.getCode() == type){
                    item.setWorkBillCode(proPlanMap.get(billId).getCode());
                }
                if (WorkOrderBillEnum.Ass.getCode() == type){
                    item.setWorkBillCode(assMap.get(billId).getCode());
                }
            }
            /*
             * =======================================关联单据逻辑赋值 end =====================================
             */
            /*
             * ======================================= 工单任务赋值 start =====================================
             */
            Long id = item.getId();
            if(ObjectUtil.isEmpty(id)){
                return;
            }
            List<Task> tasks = taskGroupByWorkOrderId.get(item.getId());
            if (ObjectUtil.isEmpty(tasks)){
                return;
            }

            // 排序
            ListUtil.sortByProperty(tasks, "sortNum");

            item.setTaskList(tasks);

            /*
             * ======================================= 工单任务赋值 end =====================================
             */
            /*
             * ======================================= 任务进度赋值 start =====================================
             */
            List<Integer> progressRateList = new ArrayList<>();
            tasks.forEach(task ->{
                int progressRate = 0;
                Integer plaNum = task.getPlaNum();
                Integer goodNum = task.getGoodNum();
                if(ObjectUtil.isNotEmpty(plaNum) && ObjectUtil.isNotEmpty(goodNum)){
                    progressRate = (100 * goodNum)/plaNum;
                }
                progressRateList.add(progressRate);
            });
            item.setProgressRateList(progressRateList);
            /*
             * ======================================= 任务进度赋值 end =====================================
             */

            /*
             * =======================================报工时长逻辑赋值 start =====================================
             */
            List<WorkReport> workReports= workReportGroupByWorkOrderId.get(id);
            if(ObjectUtil.isNotEmpty(workReports)) {
                int reportWorkTime = 0;
                for ( WorkReport workReport :workReports) {
                    if (ObjectUtil.isNotEmpty(workReport.getWorkTime())) {
                        reportWorkTime += workReport.getWorkTime();
                    }
                }
                item.setReportWorkTime(reportWorkTime);
            }
            /*
             * =======================================报工时长逻辑赋值 end =====================================
             */


        });

        return  new PageResult<>(page);
    }

    private  QueryWrapper getQueryWrapper(WorkOrderParam workOrderParam){
        QueryWrapper<WorkOrderResult> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(workOrderParam)) {
            if (!ObjectUtils.isEmpty(workOrderParam.getPlaTime())) {
                String str = workOrderParam.getPlaTime();
                String[] strArray = str.split(";");
                Date date1 = DateUtil.parse(String.valueOf(strArray[0]), "yyyy-MM-dd HH:mm");
                Date date2 = DateUtil.parse(String.valueOf(strArray[1]), "yyyy-MM-dd HH:mm");
                workOrderParam.setPlaStartTime(date1);
                workOrderParam.setPlaEndTime(date2);
            }
            // 根据计划时间 查询
            if (ObjectUtil.isNotEmpty(workOrderParam.getPlaStartTime())&&ObjectUtil.isNotEmpty(workOrderParam.getPlaEndTime())) {
                queryWrapper.between("a.pla_start_time",workOrderParam.getPlaStartTime(),workOrderParam.getPlaEndTime());
                queryWrapper.between("a.pla_end_time",workOrderParam.getPlaStartTime(),workOrderParam.getPlaEndTime());
            }
            // 根据备注 查询
            if (ObjectUtil.isNotEmpty(workOrderParam.getRemarks())) {
                queryWrapper.like("a.remarks", workOrderParam.getRemarks());
            }
            // 根据状态(未开始:-1;执行中:0;已结束:1;已取消:-2) 查询
            if (ObjectUtil.isNotEmpty(workOrderParam.getStatus())) {
                queryWrapper.eq("a.status", workOrderParam.getStatus());
            }
            // 根据多选状态字符串进行查询
            if (ObjectUtil.isNotEmpty(workOrderParam.getStatusStr()) && ArrayUtil.isNotEmpty(workOrderParam.getStatusStr().split(";"))) {
                queryWrapper.in("a.status",  Arrays.asList(workOrderParam.getStatusStr().split(";")));
            }

            // 根据工单编号 查询
            if (ObjectUtil.isNotEmpty(workOrderParam.getWorkOrderNo())) {
                queryWrapper.like("a.work_order_no", workOrderParam.getWorkOrderNo());
            }
//            // 根据下单人查询
//            if (ObjectUtil.isNotEmpty(workOrderParam.getWorkOrderNo())) {
//                queryWrapper.like("a.next_person", workOrderParam.getWorkOrderNo());
//            }
//            // 根据负责人查询
//            if (ObjectUtil.isNotEmpty(workOrderParam.getWorkOrderNo())) {
//                queryWrapper.like("a.person_charge", workOrderParam.getWorkOrderNo());
//            }
        }
        queryWrapper.orderByDesc("a.create_time");

        return queryWrapper;
    }

    @Override
    public List<WorkOrderResult> list(WorkOrderParam workOrderParam) {

        return baseMapper.list(workOrderParam);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(WorkOrderParam workOrderParam) {
        /*
         * =================================工单数据处理 START=============================
         */
        WorkOrder workOrder = new WorkOrder();
        //工单编号不能重复
        checkParam(workOrderParam,false);
        //校验工单编号非空
        if(ObjectUtil.isEmpty(workOrderParam.getWorkOrderNo()))
        {
            workOrderParam.setWorkOrderNo(AutoCode.getCodeByService("dw_work_order", this.getClass(), 1));
        }
        if(ObjectUtil.isEmpty(workOrderParam.getNextPerson())) {
            workOrderParam.setNextPerson(LoginContextHolder.me().getSysLoginUserId());
        }
        if(ObjectUtil.isEmpty(workOrderParam.getPersonCharge())) {
            workOrderParam.setPersonCharge(LoginContextHolder.me().getSysLoginUserId());
        }
        if(ObjectUtil.isEmpty(workOrderParam.getOrderTime()))
        {
            Date date = new Date();
            workOrderParam.setOrderTime(date);
        }
        BeanUtil.copyProperties(workOrderParam, workOrder);


        // 默认工单类型（顺序型工单）
        if(ObjectUtil.isEmpty(workOrderParam.getType())){
            workOrder.setType(WorkOrderTypeEnum.SEQUENTIAL_WORK_ORDER.getCode());
        }

        // 默认状态（未开始）
        if (ObjectUtil.isEmpty(workOrderParam.getStatus())){
            workOrder.setStatus(WorkOrderStatusEnum.NOT_START.getCode());
        }
        // 根据产品，对产品类型进行赋值
        if(ObjectUtil.isNotEmpty(workOrderParam.getProId())){
            workOrderParam.getProId();
            Pro pro = proService.getById(workOrderParam.getProId());
            QueryWrapper queryWrapper=new QueryWrapper();
            queryWrapper.eq("id",pro.getWorkRouteId( ));
            List<WorkRoute>workRouteList= workRouteService.list(queryWrapper);
            QueryWrapper queryWrapper1=new QueryWrapper();
            queryWrapper.eq("work_route_id",pro.getWorkRouteId( ));
            List<WorkStepRoute>workStepRoutes=workStepRouteService.list(queryWrapper1);
            // 如果产品类型为空且查询出的产品类型不为空
            if (ObjectUtil.isEmpty(workOrder.getProTypeId()) && ObjectUtil.isNotEmpty(pro.getProTypeId())){
                workOrder.setProTypeId(pro.getProTypeId());
            }
        }
        if(ObjectUtil.isEmpty(workOrderParam.getProId())){
            throw new ServiceException(WorkOrderExceptionEnum.NOT_NULL_PRO_ID);
        }

        // 工单时间处理
        if(ObjectUtil.isNotEmpty(workOrderParam.getPlaTime())){
            String[] plaTimeArr = workOrderParam.getPlaTime().split(";");

            if(ObjectUtil.isNotEmpty(plaTimeArr) && plaTimeArr.length == 2){
                // 计划开始时间赋值
                workOrder.setPlaStartTime(DateUtil.parse(plaTimeArr[0], "yyyy-MM-dd HH:mm"));
                // 计划结束时间赋值
                workOrder.setPlaEndTime(DateUtil.parse(plaTimeArr[1], "yyyy-MM-dd HH:mm"));
            }

        }

        // 工单数据进行插入操作
        this.save(workOrder);
        /*
         *================================= 工单数据处理 END =======================================
         */

        /*
         *  ================================= 任务数据处理 start =================================
         */
        // 任务列表是否为空
        if(ObjectUtil.isNotEmpty(workOrderParam.getTaskList())){
            List<Task> taskList = workOrderParam.getTaskList();
            taskList.forEach(item->{
                //校验工序不能为空
                if (ObjectUtil.isEmpty(item.getWorkStepId())) {
                    throw new ServiceException(WorkOrderExceptionEnum.NOT_NULL_TASK_WORK_STEP_ID);
                }
                //校验任务计划开始时间不能为空
                if (ObjectUtil.isEmpty(item.getPlaStartTime())){
                    throw new ServiceException(WorkOrderExceptionEnum.NOT_NULL_TASK_STR_TIME);
                }
                //校验任务计划结束时间不能为空
                if (ObjectUtil.isEmpty(item.getPlaEndTime())){
                    throw new ServiceException(WorkOrderExceptionEnum.NOT_NULL_TASK_END_TIME);
                }
                // 默认状态（未开始）
                if (ObjectUtil.isEmpty(item.getStatus())){
                    item.setStatus(WorkOrderStatusEnum.NOT_START.getCode());
                }
                // 设置工单id
                if(ObjectUtil.isEmpty(item.getWorkOrderId())){
                    item.setWorkOrderId(workOrder.getId());// 缺少判空，如果前端有值，那么会被后端覆盖（从目前的业务角度上看是没错的，但不建议这么写）
                }
                if(ObjectUtil.isEmpty(item.getGoodNum())){
                    item.setGoodNum(0);// 缺少判空，如果前端有值，那么会被后端覆盖（从目前的业务角度上看是没错的，但不建议这么写）
                }
                if(ObjectUtil.isEmpty(item.getBadNum())){
                    item.setBadNum(0);// 缺少判空，如果前端有值，那么会被后端覆盖（从目前的业务角度上看是没错的，但不建议这么写）
                }

                // 临时代码（之后调用编码生成器中的接口）
                if (ObjectUtil.isEmpty(item.getCode())){
//                    item.setCode(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"))+"task"+taskList.indexOf(item));// 缺少判空，如果前端有值，那么会被后端覆盖（从目前的业务角度上看是没错的，但不建议这么写）
                    item.setCode(AutoCode.getCodeByService("dw_task", taskService.getClass(), 0));
                }
                // 对产品进行赋值
                if(ObjectUtil.isNotEmpty(workOrder.getProId())){
                    item.setProId(workOrder.getProId());
                }

                // 对产品类型进行赋值
                if(ObjectUtil.isNotEmpty(workOrder.getProTypeId())){
                    item.setProTypeId(workOrder.getProTypeId());
                }
                taskService.save(item);
            });
            /*
             * ================================= 任务数据处理 end =========================================
             */

            // 如果是【顺序型】工单逻辑到此结束
            if(WorkOrderTypeEnum.SEQUENTIAL_WORK_ORDER.getCode().equals(workOrder.getType())){
                return;
            }

            /*
             * ================================= 工单任务关系表（待调整） 数据处理 start ===============================
             */
            // 1、准备容器
            List<WorkOrderTask> workOrderTasks = new ArrayList<>();
            for(int i = 0; i < taskList.size(); i ++){
                // 工单关系表实例
                WorkOrderTask workOrderTask = new WorkOrderTask();
                // 工单id进行赋值
                workOrderTask.setWorkOrderId(workOrder.getId());
                // 第一个工单关系数据的源是id为0
                if(i == 0){
                    workOrderTask.setSourceTaskId(0L);
                }else {
                    workOrderTask.setSourceTaskId(taskList.get(i-1).getId());
                }
                // 最后一个targetTaskId是1
                if(i ==  taskList.size()-1){
                    workOrderTask.setTargetTaskId(1L);
                }else {
                    workOrderTask.setTargetTaskId(taskList.get(i).getId());
                }
                // 放进容器中
                workOrderTasks.add(workOrderTask);
            }
            // 执行工单关系的批量插入操作
            workOrderTaskService.saveBatch(workOrderTasks);
            /*
             * ================================= 工单任务关系表（待调整） 数据处理 end =================================
             */
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<WorkOrderParam> workOrderParamList) {
        List<WorkOrder> workOrderList=this.list();
        Map<Long,WorkOrder> workOrderMap =workOrderList.stream().collect(Collectors.toMap(WorkOrder::getId, a -> a, (k1, k2) -> k1));
        //若存在工单存在工单单据则不能删除
        workOrderParamList.forEach(workOrderParam->{
            if (ObjectUtil.isNotEmpty(workOrderMap.get(workOrderParam.getId()).getBillId())){
                throw new ServiceException(11,"工单存在工单单据，不能删除");
            }
        });
        // 查询出所有的任务
        List<Task> taskList = taskService.list();
        // 将任务按照工单进行分组
        Map<Long,List<Task>> taskGroupByWorkOrderId = taskList.stream()
                .collect(Collectors.groupingBy(Task::getWorkOrderId));
        // 查询出所有的报工
        List<WorkReport> workReportList = workReportService.list();
        // 将报工按照工单进行分组
        Map<Long,List<WorkReport>> workReportGroupByWorkOrderId = workReportList.stream()
                .collect(Collectors.groupingBy(WorkReport::getWorkOrderId));
        // 查询出所有的工单任务关系
        List<WorkOrderTask> workOrderTaskList = workOrderTaskService.list();
        // 将工单任务关系按照工单进行分组
        Map<Long,List<WorkOrderTask>> workOrderTaskGroupByWorkOrderId = workOrderTaskList.stream()
                .collect(Collectors.groupingBy(WorkOrderTask::getWorkOrderId));
        if (ObjectUtil.isEmpty(workOrderParamList)){
            return;
        }
        List<Long>workOrderIds=new ArrayList<>();
        List<Long>taskIds=new ArrayList<>();
        List<Long>workReportIds=new ArrayList<>();
        List<Long>workOrderTaskIds=new ArrayList<>();
        workOrderParamList.forEach(workOrderParam -> {
            workOrderIds.add(workOrderParam.getId());
            List<Task> tasks = taskGroupByWorkOrderId.get(workOrderParam.getId());
            if(ObjectUtil.isNotEmpty(tasks)){
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
            }

            List<WorkReport> workReports = workReportGroupByWorkOrderId.get(workOrderParam.getId());
            if(ObjectUtil.isNotEmpty(workReports)) {
                workReports.forEach(workReport -> {
                    workReportIds.add(workReport.getId());
                });
            }

            List<WorkOrderTask> workOrderTasks = workOrderTaskGroupByWorkOrderId.get(workOrderParam.getId());
            if (ObjectUtil.isNotEmpty(workOrderTasks)){
                workOrderTasks.forEach(workOrderTask -> {
                    workOrderTaskIds.add(workOrderTask.getId());
                });
            }
        });
        this.removeByIds(workOrderIds);
        taskService.removeByIds(taskIds);
        workReportService.removeByIds(workReportIds);
        workOrderTaskService.removeByIds(workOrderTaskIds);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(WorkOrderParam workOrderParam) {
        /*
         * =================================工单数据处理 START=============================
         */
        WorkOrder workOrder = this.queryWorkOrder(workOrderParam);
        //工单编号不能重复
        checkParam(workOrderParam,true);
        // 如果工单类型不允许修改
        if(ObjectUtil.isNotEmpty(workOrderParam.getType())){
            if (!workOrderParam.getType().equals(workOrder.getType())){
                throw new ServiceException(WorkOrderExceptionEnum.NOT_EDIT_WORK_ORDER_TYPE);
            }
        }
        //编辑状态
        if (WorkOrderStatusEnum.CANCELED.getCode().equals(workOrder.getStatus())){
            throw new ServiceException(WorkOrderExceptionEnum.NOT_EDIT_WORK_ORDER_STATUS);
        }else {
            if (WorkOrderStatusEnum.revoke_action.getCode().equals(workOrderParam.getStatus())) {
                if (WorkOrderStatusEnum.EXECUTION.getCode().equals(workOrder.getStatus())) {
                    workOrderParam.setStatus(WorkOrderStatusEnum.NOT_START.getCode());
                } else if (WorkOrderStatusEnum.FINISH.getCode().equals(workOrder.getStatus())) {
                    workOrderParam.setStatus(WorkOrderStatusEnum.EXECUTION.getCode());
                } else {
                    workOrderParam.setStatus(workOrder.getStatus());
                }
            }
        }


        // 根据产品，对产品类型进行赋值
        if(ObjectUtil.isNotEmpty(workOrderParam.getProId())){
            Pro pro = proService.getById(workOrderParam.getProId());
            // 如果产品类型为空且查询出的产品类型不为空
            if (ObjectUtil.isNotEmpty(workOrder.getProTypeId()) && ObjectUtil.isNotEmpty(pro.getProTypeId())){
                workOrderParam.setProTypeId(pro.getProTypeId());
            }
        }

        // 工单时间处理
        if(ObjectUtil.isNotEmpty(workOrderParam.getPlaTime())){
            String[] plaTimeArr = workOrderParam.getPlaTime().split(";");

            if(ObjectUtil.isNotEmpty(plaTimeArr) && plaTimeArr.length == 2){
                // 计划开始时间赋值
                workOrder.setPlaStartTime(DateUtil.parse(plaTimeArr[0], "yyyy-MM-dd HH:mm"));
                // 计划结束时间赋值
                workOrder.setPlaEndTime(DateUtil.parse(plaTimeArr[1], "yyyy-MM-dd HH:mm"));
            }

        }
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        //状态为未开始
        if (WorkOrderStatusEnum.NOT_START.getCode().equals(workOrderParam.getStatus())) {
            workOrderParam.setFactStaTime(null);
            workOrderParam.setFactEndTime(null);
        }
        //状态为执行中
        if (WorkOrderStatusEnum.EXECUTION.getCode().equals(workOrderParam.getStatus())) {
            if (ObjectUtil.isNotEmpty(workOrderParam.getFactStaTime())) {
                //结束时间滞空
                workOrderParam.setFactEndTime(null);
            }
            if (ObjectUtil.isEmpty(workOrderParam.getFactStaTime())) {
                //把当前时间赋给开始时间
                workOrderParam.setFactStaTime(DateUtil.parse(dateFormat.format(date)));
                //结束时间滞空
                workOrderParam.setFactEndTime(null);
            }
        }
        //状态为已结束
        if (WorkOrderStatusEnum.FINISH.getCode().equals(workOrderParam.getStatus())) {

            if (ObjectUtil.isEmpty(workOrderParam.getFactEndTime())) {

                //把当前时间赋给实际结束时间
                workOrderParam.setFactEndTime(DateUtil.parse(dateFormat.format(date)));
            }
        }
        BeanUtil.copyProperties(workOrderParam, workOrder);
        this.updateById(workOrder);
        /*
         * =================================工单数据处理 END=============================
         */

        /*
         *  ================================= 任务数据处理 start =================================
         */

        // 任务map数据准备（防止循环调用sql）
        Map<Long,Task> dbTaskMap = new HashMap<>();
        taskService.list().forEach(item->{
            dbTaskMap.put(item.getId(), item);
        });

        // 定义新增、编辑容器
        List<Task> addTaskList = new ArrayList<>();
        List<Task> editTaskList = new ArrayList<>();
        List<Long> editTaskIdList = new ArrayList<>();

        // 无id则为新增，有id则为编辑
        List<Task> paramTaskList = workOrderParam.getTaskList();
        if(ObjectUtil.isNotEmpty(paramTaskList)){
            paramTaskList.forEach(item->{
                if(ObjectUtil.isEmpty(item.getId())){
                    addTaskList.add(item);
                } else {
                    editTaskList.add(item);
                    editTaskIdList.add(item.getId());
                }
            });
        }


        // 数据库中不在编辑id容器中的，就是要被删除的
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Task::getWorkOrderId, workOrder.getId());
        if(ObjectUtil.isNotEmpty(editTaskList)){
            queryWrapper.lambda().notIn(Task::getId, editTaskIdList);
        }
        List<Task> delTaskList = taskService.list(queryWrapper);


        // 批量新增以及数据初始化
        if(ObjectUtil.isNotEmpty(addTaskList)){
            // 将任务list遍历设置工单id
            addTaskList.forEach(item->{
                item.setWorkOrderId(workOrder.getId());
                // 对产品进行赋值
                if(ObjectUtil.isNotEmpty(workOrder.getProId())){
                    item.setProId(workOrder.getProId());
                }
                // 对产品类型进行赋值
                if(ObjectUtil.isNotEmpty(workOrder.getProTypeId())){
                    item.setProTypeId(workOrder.getProTypeId());
                }
                if (ObjectUtil.isEmpty(item.getCode())){
                    item.setCode(AutoCode.getCodeByService("dw_task", taskService.getClass(), 0));
                }
                taskService.save(item);
            });


        }

        // 批量更新任务数据（注意：防止有字段支持空更新）
        if(ObjectUtil.isNotEmpty(editTaskList)){
            List<Task> dbEditTaskList = new ArrayList<>();
            editTaskList.forEach(item->{
                // 设置工单id
                item.setWorkOrderId(workOrder.getId());
                // 对产品进行赋值
                if(ObjectUtil.isNotEmpty(workOrder.getProId())){
                    item.setProId(workOrder.getProId());
                }
                // 对产品类型进行赋值
                if(ObjectUtil.isNotEmpty(workOrder.getProTypeId())){
                    item.setProTypeId(workOrder.getProTypeId());
                }
                // 防止有字段支持空更新
                if (ObjectUtil.isNotEmpty(item.getId())){
                    Task dbTask = dbTaskMap.get(item.getId());
                    if (ObjectUtil.isNull(dbTask)) {
                        throw new ServiceException(TaskExceptionEnum.NOT_EXIST);
                    }
                    BeanUtil.copyProperties(item, dbTask);
                    dbEditTaskList.add(dbTask);
                }

            });
            taskService.updateBatchById(dbEditTaskList);
        }


        // 执行任务的批量删除以及关联数据
        if(ObjectUtil.isNotEmpty(delTaskList)){
            List<Long> delTaskIdList = new ArrayList<>();
            delTaskList.forEach(item->{
                delTaskIdList.add(item.getId());
            });

            // 批量删除关联数据逻辑(报工数据删除)
            QueryWrapper<WorkReport> workReportQueryWrapper = new QueryWrapper<>();
            workReportQueryWrapper.lambda().in(WorkReport::getTaskId, delTaskIdList);
            List<WorkReport> workReports = workReportService.list(workReportQueryWrapper);
            if(ObjectUtil.isNotEmpty(workReports)){
                List<Long> delWorkReportList = new ArrayList<>();
                workReports.forEach(workReport -> {
                    delWorkReportList.add(workReport.getId());
                });
                workReportService.removeByIds(delWorkReportList);
            }

            // 批量删除任务
            taskService.removeByIds(delTaskIdList);
        }

        /*
         * ================================= 任务数据处理 end =========================================
         */

        // 如果是【顺序型】工单逻辑到此结束
        if(WorkOrderTypeEnum.SEQUENTIAL_WORK_ORDER.getCode().equals(workOrder.getType())){
            return;
        }

        /*
         * ================================= 工单任务关系表（待调整） 数据处理 start ===============================
         */



        /*
         * ================================= 工单任务关系表（待调整） 数据处理 end =================================
         */


    }

    @Override
    public WorkOrder detail(WorkOrderParam workOrderParam) {
        return this.queryWorkOrder(workOrderParam);
    }

    /**
     * 获取工单表
     *
     * @author czw
     * @date 2022-05-25 10:31:14
     */
    private WorkOrder queryWorkOrder(WorkOrderParam workOrderParam) {
        WorkOrder workOrder = this.getById(workOrderParam.getId());
        if (ObjectUtil.isNull(workOrder)) {
            throw new ServiceException(WorkOrderExceptionEnum.NOT_EXIST);
        }
        return workOrder;
    }

    @Override
    public void export(WorkOrderParam workOrderParam) {
        List<WorkOrderResult> list = baseMapper.page(getQueryWrapper(workOrderParam));
//        List<WorkOrderResult> workOrderExports = new ArrayList<>();
//        for(WorkOrderResult workOrderResult:list){
//            workOrderExports.add(workOrderResult);
//        }
        PoiUtil.exportExcelWithStream("SnowyWorkOrder.xls", WorkOrderResult.class, list);
    }

    /**
     * 校验参数，检查是否存在相同的名称和编码
     *
     * @author xuyuxiang
     * @date 2020/3/25 21:23
     */
    private void checkParam(WorkOrderParam workOrderParam, boolean isExcludeSelf) {
        Long id = workOrderParam.getId();
        String workOrderNo = workOrderParam.getWorkOrderNo();

        LambdaQueryWrapper<WorkOrder> queryWrapperByNo = new LambdaQueryWrapper<>();
        queryWrapperByNo.eq(WorkOrder::getWorkOrderNo, workOrderNo);
        //如果是编辑，校验名称编码时排除自身
        if (isExcludeSelf) {
            queryWrapperByNo.ne(WorkOrder::getId, id);
        }

        int countByNo = this.count(queryWrapperByNo);


        if (countByNo >= 1) {
            throw new ServiceException(WorkOrderExceptionEnum.NOT_IDENTICAL_WORK_ORDER_NO);
        }

    }

}